Day 15: 데코레이터
데코레이터란?
함수를 감싸서 실행 전후에 추가 동작을 삽입하는 패턴입니다.
import time
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
elapsed = time.time() - start
print(f"{func.__name__} 실행 시간: {elapsed:.4f}초")
return result
return wrapper
@timer
def slow_function():
time.sleep(1)
return "완료"
slow_function() # slow_function 실행 시간: 1.00xx초
functools.wraps
원래 함수의 메타데이터를 보존합니다.
from functools import wraps
def log_call(func):
@wraps(func)
def wrapper(*args, **kwargs):
print(f"호출: {func.__name__}({args}, {kwargs})")
return func(*args, **kwargs)
return wrapper
@log_call
def add(a, b):
"""두 수를 더합니다."""
return a + b
print(add.__name__) # add (wraps 없으면 wrapper)
print(add.__doc__) # 두 수를 더합니다.
매개변수가 있는 데코레이터
def repeat(n):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for _ in range(n):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def greet(name):
print(f"안녕, {name}!")
greet("철수")
# 안녕, 철수! (3번 출력)
실용적 데코레이터: 캐시
from functools import lru_cache
@lru_cache(maxsize=128)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(50)) # 12586269025 (빠르게 계산)
오늘의 연습문제
- 함수 호출 횟수를 세는
count_calls데코레이터를 만드세요. - 반환값을 검증하는
validate_positive데코레이터를 만드세요 (음수면 에러). - 함수 실행을 자동으로 재시도하는
retry(max_attempts)데코레이터를 만드세요.